#include "type.h"
#include "const.h"
#include "protect.h"
#include "tty.h"
#include "console.h"
#include "string.h"
#include "proc.h"
#include "global.h"
#include "keyboard.h"
#include "proto.h"

#define TTY_FIRST	(tty_table)
#define TTY_END		(tty_table + NR_CONSOLES)

// 文件内函数
PRIVATE void	init_tty(TTY* p_tty);
PRIVATE void	tty_do_read(TTY* p_tty);
PRIVATE void	tty_do_write(TTY* p_tty);
PRIVATE void put_key(TTY* p_tty, t_32 key);

/*----------------------------------------------------
函数名：void task_tty()
功能：  终端任务
------------------------------------------------------*/
PUBLIC void task_tty()
{
    TTY* p_tty;

    init_keyboard();

    for (p_tty = TTY_FIRST; p_tty < TTY_END; p_tty++) {
        init_tty(p_tty);
    }

    select_console(0);

    while (1) {
        for (p_tty = TTY_FIRST; p_tty < TTY_END; p_tty++) {
            tty_do_read(p_tty);
            tty_do_write(p_tty);
        }
    }
}

/*----------------------------------------------------
函数名：void init_tty(TTY* p_tty)
功能：  终端初始化
------------------------------------------------------*/
PRIVATE void init_tty(TTY* p_tty)
{
    p_tty->inbuf_count = 0;
    p_tty->p_inbuf_head = p_tty->p_inbuf_tail = p_tty->in_buf;

    init_screen(p_tty);
}

/*----------------------------------------------------
函数名：void in_process(TTY* p_tty, t_32 key)
功能：  处理键盘扫描码
------------------------------------------------------*/
PUBLIC void in_process(TTY* p_tty, t_32 key)
{
    if (!(key & FLAG_EXT)) {
        if (p_tty->inbuf_count < TTY_IN_BYTES) {
            *(p_tty->p_inbuf_head) = key;
            p_tty->p_inbuf_head++;
            if (p_tty->p_inbuf_head == p_tty->in_buf + TTY_IN_BYTES) {
                p_tty->p_inbuf_head = p_tty->in_buf;
            }
            p_tty->inbuf_count++;
        }
    }
    else {
        int raw_code = key & MASK_RAW;
        switch (raw_code) {
        case ENTER:
            put_key(p_tty, '\n');
            break;
        case BACKSPACE:
            put_key(p_tty, '\b');
            break;
        case UP:
			if ((key & FLAG_SHIFT_L) || (key & FLAG_SHIFT_R)) {	/* Shift + Up */
				scroll_screen(p_tty->p_console, SCROLL_SCREEN_UP);
			}
            break;
        case DOWN:
			if ((key & FLAG_SHIFT_L) || (key & FLAG_SHIFT_R)) {	/* Shift + Down */
				scroll_screen(p_tty->p_console, SCROLL_SCREEN_DOWN);
            }
			break;
        case F1:
		case F2:
		case F3:
		case F4:
		case F5:
		case F6:
		case F7:
		case F8:
		case F9:
		case F10:
		case F11:
		case F12:
            if ((key & FLAG_ALT_L) || (key & FLAG_ALT_R)) {
                select_console(raw_code - F1);
            }
        default:
            break;
        }
    }
}

/*----------------------------------------------------
函数名：void put_key(TTY* p_tty, t_32 key)
功能：  向 tty 缓冲区写入特殊功能字符
------------------------------------------------------*/
PRIVATE void put_key(TTY* p_tty, t_32 key)
{
    if (p_tty->inbuf_count < TTY_IN_BYTES) {
		*(p_tty->p_inbuf_head) = key;
		p_tty->p_inbuf_head++;
		if (p_tty->p_inbuf_head == p_tty->in_buf + TTY_IN_BYTES) {
			p_tty->p_inbuf_head = p_tty->in_buf;
		}
		p_tty->inbuf_count++;
	}
}

/*----------------------------------------------------
函数名：void tty_do_read(TTY* p_tty)
功能：  终端读操作
------------------------------------------------------*/
PRIVATE void tty_do_read(TTY* p_tty)
{
    if (is_current_console(p_tty->p_console)) {
        keyboard_read(p_tty);
    }
}

/*----------------------------------------------------
函数名：void tty_do_write(TTY* p_tty)
功能：  终端写操作
------------------------------------------------------*/
PRIVATE void tty_do_write(TTY* p_tty)
{
    if (p_tty->inbuf_count) {
        char ch = *(p_tty->p_inbuf_tail);
        p_tty->p_inbuf_tail++;
        if (p_tty->p_inbuf_tail == p_tty->in_buf + TTY_IN_BYTES) {
            p_tty->p_inbuf_tail = p_tty->in_buf;
        }
        p_tty->inbuf_count--;

        out_char(p_tty->p_console, ch);
    }
}

/*----------------------------------------------------
函数名：void tty_write(TTY* p_tty, char* buf, int len)
功能：  直接将字符显示在控制台
------------------------------------------------------*/
PUBLIC void tty_write(TTY* p_tty, char* buf, int len)
{
    char *p = buf;
    int i = len;

    while (i) {
        out_char(p_tty->p_console, *p++);
        i--;
    }
}

/*----------------------------------------------------
函数名：int sys_write(char* buf, int len, PROCESS* p_proc)
功能：  write 系统调用的内核部分
------------------------------------------------------*/
PUBLIC int sys_write(char* buf, int len, PROCESS* p_proc)
{
	tty_write(&tty_table[p_proc->nr_tty], buf, len);
	return 0;
}